require 'digest/sha1'

class Student < ActiveRecord::Base

  attr_accessible :id, :email, :lastfaillogin, :lastlogin, :lastupdated, :login, :loginfailcount, :registeredat, :reset_password, :hashed_password, :salt, :password
  validates_length_of :login, :within => 5..20
  validates_length_of :password, :minimum => 6
  validates_presence_of :login, :email, :password, :salt

  #validates_confirmation_of :password
  validates_uniqueness_of :login, :email, :message => (I18n.t "register.error.badloginname")
  validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => (I18n.t "register.error.bademail")

  #attr_protected :login
  attr_accessor :password

  #relation
  has_one :student_profile
  has_and_belongs_to_many :student_group_links
  has_and_belongs_to_many :student_activities
  has_many :library_borrow_records

  #call the callbacks
  before_save :update_timestamp
  before_update :update_profile_timestamp


  def self.authenticate(login, pwd)
    u = find(:first, :conditions => ["login = ?", login])
    return nil if u.nil?
    if Student.encrypt(pwd, u.salt)==u.hashed_password
      u.update_attribute(:lastlogin, Time.now)
      if u.reset_password
        u.update_attribute(:reset_password, nil)
      end
      return u
    else
      u.update_attribute(:loginfailcount, u.loginfailcount.to_i + 1)
      u.update_attribute(:lastfaillogin, Time.now)
      return nil
    end
  end

  def self.check_email(id, email)
    where("email = #{email} AND id != #{id}").first
  end

  def self.check_login(id, login)
    where("login = #{login} AND id != #{id} ").first
  end

  def update_profile_timestamp
    self.lastupdated = Time.now
  end

  def update_timestamp
    if self.registeredat.nil?
      self.registeredat = Time.now
    end
  end

  def self.encrypt(pwd, salt)
    Digest::SHA1.hexdigest(pwd+salt)
  end

  def password=(pwd)
    @password = pwd
    self.salt = Student.random_string(10) if !self.salt?
    self.hashed_password = Student.encrypt(@password, self.salt)
    self.lastupdated = Time.now
  end

  def change_password(pwd)
    @password = pwd
    self.salt = Student.random_string(10) if !self.salt?
    self.hashed_password = Student.encrypt(@password, self.salt)
    self.lastupdated = Time.now
    self.save
    Notifications.reset_password(self.email, self.login).deliver
  end

  def self.random_string(len)
    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
    newpass = ""
    1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
    return newpass
  end

  def new_password_request
    new_pass = Student.random_string(64)
    self.update_attribute(:reset_password, new_pass)
    Notifications.forgot_password(self.email, self.login, new_pass).deliver
  end

  #do a check login name existed or not, check reset_password as a key
  def self.check_reset_password(login, key)
    return false if login.blank? and key.blank?
    u = Student.find_by_login_and_reset_password(login, key)
    return false if u.nil?
    return u
  end

  def update_profile(params)
    student_profile = self.student_profile
    if student_profile.nil?
      u = params[:student_profile]
      u[:student_id] = self.id
      student_profile = StudentProfile.new(u)
      student_profile.save
    else
      StudentProfile.update(student_profile.id.to_i, params[:student_profile])
    end
    up_student = params[:student]
    is_login_existed = Student.where("login = '#{up_student[:login].to_s}' AND id!='#{self.id}'").first
    is_email_existed = Student.where("email = '#{up_student[:email].to_s}' AND id!='#{self.id}'").first
    message=[]
    #update login
    if is_login_existed.nil?
      self.update_attribute(:login, up_student[:login])
    else
      message << I18n.t("updateprofile.error.loginexisted")
    end
    #update email
    if is_email_existed.nil?
      self.update_attribute(:email, up_student[:email])
    else
      message << I18n.t("updateprofile.error.emailexisted")
    end
    #update password
    current_password = up_student[:password].to_s
    new_hashed_pwd = Student.encrypt(current_password, self.salt).to_s
    newpwd = up_student[:newpassword].to_s
    newpwd_confirm = up_student[:newpassword].to_s
    if current_password!="" #check if user inputs current password
      if new_hashed_pwd==self.hashed_password
        if newpwd == newpwd_confirm
          self.change_password(up_student[:newpassword])
        else
          message << I18n.t("updateprofile.error.passwordnotmatch")
        end
      else
        message << I18n.t("updateprofile.error.wrongpassword")
      end
    end
    if message!=nil
      message
    else
      nil
    end
  end

  def delete_all_records
    if StudentGroupLink.check_admin(self.id)
      nil
    end
      StudentProfile.delete_all(:student_id => self.id)
      StudentActivity.delete_all(:student_id => self.id)
      StudentGroupLink.delete_all(:student_id => self.id)
      LibraryBorrowRecord.delete_all(:student_id => self.id)
      self.delete
      rescue
        true
      end
end
